<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/9/19
 * Time: 14:40
 */

namespace App\Game;


use App\Models\Def\MainGamePlat;
use App\Models\Inf\Player;
use App\Models\Log\PlayerBetFlow;
use Carbon\Carbon;

class Record
{
    public $plat;

    public $lines;

    public $defTimezone = 'Asia/Shanghai';

    public function __construct($platName)
    {
        $plat = '\\App\\Game\\' . $platName;
        if (class_exists($plat)) {
            $class = new \ReflectionClass($plat);
            $this->plat = $class->newInstanceArgs();
        } else {
            die("此平台类型不存在");
        }

        $this->initPlatAttribute($platName);
        $this->initPlatParams();
    }

    /**
     * gameapi
     * 2019/1/7 13:44
     * Administrator
     * initAttribute
     * 初始化平台类型属性
     * @param $plat
     * @return object
     */
    private function initPlatAttribute($plat)
    {
        foreach (config('game.' . $plat) as $key => $value) {
            if($key=='line'){
                $this->lines=$value;

            }elseif($key=='updateFiled'){
                $this->plat->$key=$value;
            }else{
                $this->plat->$key=$value;
            }

        }
        return $this->plat;

    }

    /**
     * gameapi
     * 2019/1/7 13:45
     * Administrator
     * dynamicInitLineAttribute
     * 动态初始化平台线路属性
     * @param array $line
     */
    private function dynamicInitLineAttribute(array $line)
    {
        if(array_key_exists('lineName',$line)){
            foreach ($line as $key =>$value){
                $this->plat->$key=$value;
            }
        }else{
            foreach ($line as $key =>$value){
                $this->plat->$key=$value;
            }
            $this->plat->lineName=$this->plat->platName;
        }
    }

    /**
     * gameapi
     * 2019/1/14 15:13
     * Administrator
     * initPlatParams
     * 平台参数初始化
     */
    private function initPlatParams()
    {
        if (method_exists($this->plat, 'initParams')) {
            $this->plat->initParams();
        }
    }

    /**
     * gameapi
     * 2019/1/7 13:45
     * Administrator
     * getBetRecord
     * 获取记录
     * @param Carbon $startTime
     * @param Carbon $endTime
     */
    public function getBetRecord(Carbon $startTime, Carbon $endTime)
    {
        foreach ($this->lines as $line){
            $this->dynamicInitLineAttribute($line);
            $timezone = $this->getPlatTimezone();
            $times = $this->parseDateInterval($startTime, $endTime);
            foreach ($times as $time) {
                $start = Carbon::parse($time['date'] . ' ' . $time['start'], $timezone);
                $end = Carbon::parse($time['date'] . ' ' . $time['end'], $timezone);
                $originalData = $this->plat->curlGetBetRecord($start, $end);
                $this->plat->adds = array_merge($this->plat->adds, ['pull_at' => (clone $end)->timezone($this->defTimezone)->toDateTimeString()]);
                if (is_array($originalData)) {
                    try{
                        $items = $this->updateFiled($originalData);
                        $this->save($items);
                    }catch (\Exception $e){
                        $err = [
                            'code' => $e->getCode(),
                            'msg'  => $e->getMessage(),
                            'file'    => $e->getFile(),
                            'line'   => $e->getLine()
                        ];
                        file_put_contents('/home/gameapi/storage/logs/test.log', 'getRecord_error...'.json_encode($err).PHP_EOL, FILE_APPEND);
                    }
                }

            }
        }

    }


    /**
     * gameapi
     * 2018/9/20 21:30
     * Administrator
     * parseTimeInterval
     * 获取时间段数组，大于一天的拆分成以一天为单位的数组
     * @param Carbon $startTime
     * @param Carbon $endTime
     * @return array
     */
    public function parseDateInterval(Carbon $startTime, Carbon $endTime)
    {
        list($startTime, $endTime) = $this->setPlatTimezone($startTime, $endTime);

        $timeArray = [];
        $startDate = (clone $startTime)->startOfDay();
        $diffDays = $startDate->diffInDays($endTime, false);

        for ($i = 0; $i <= $diffDays; $i++) {
            $date = (clone $startTime)->addDay($i)->format('Y-m-d');
            if ($diffDays > 0) {
                if ($i == 0) {
                    $start = $startTime->format('H:i:s');
                    $end = '23:59:59';
                } elseif ($i == $diffDays) {
                    $start = '00:00:00';
                    $end = $endTime->format('H:i:s');
                } else {
                    $start = '00:00:00';
                    $end = '23:59:59';
                }
            } else {
                $start = $startTime->format('H:i:s');
                $end = $endTime->format('H:i:s');
            }
            $timeArray[] = compact('date', 'start', 'end');
        }

        return $timeArray;
    }


    /**
     * gameapi
     * 2018/9/20 14:10
     * Administrator
     * getPlatTimeInterval
     * 设置平台社区
     * @param Carbon $startTime
     * @param Carbon $endTime
     * @return array
     */
    private function setPlatTimezone(Carbon $startTime, Carbon $endTime)
    {
        if (!property_exists($this->plat, 'timezone')) {
            $this->plat->timezone = $this->defTimezone;
        } else {
            if (empty($this->plat->timezone)) {
                $this->plat->timezone = $this->defTimezone;
            }
        }

        $startTime->timezone($this->plat->timezone);
        $endTime->timezone($this->plat->timezone);

        /*if (property_exists($this->plat, 'format')) {
            $startTime = $startTime->format($this->plat->format);
            $endTime = $endTime->format($this->plat->format);
        } else {
            $startTime = $startTime->toDateTimeString();
            $endTime = $endTime->toDateTimeString();
        }*/

        return [$startTime, $endTime];
    }

    /**
     * gameapi
     * 2018/9/21 17:42
     * Administrator
     * getPlatTimezone
     * 获取平台时区
     * @return mixed
     */
    public function getPlatTimezone()
    {
        if (!property_exists($this->plat, 'timezone')) {
            $this->plat->timezone = $this->defTimezone;
        } else {
            if (empty($this->plat->timezone)) {
                $this->plat->timezone = $this->defTimezone;
            }
        }
        return $this->plat->timezone;
    }

    /**
     * gameapi
     * 2018/9/20 14:37
     * Administrator
     * updateFiled
     * 修改需要变更得字段，格式为 [需要修改得字段=>修改后得字段]
     * @param array $items 数据
     * @param array $updates 修改数组
     * @param array $adds 添加元素
     * @return array
     */
   public function updateFiled(array $items = [], array $updates = [], array $adds = [])
    {
        foreach ($items as $k => $data) {
            $apiData = $data;
            $updates = $this->plat->updateFiled['default'];
            //1.个别平台需要根据数据类型，变更修改字段
            if (method_exists($this->plat, 'changeUpdateFiled')) {
                $this->plat->changeUpdateFiled($apiData);
            }

            //2.映射修改字段
            $data = $this->mapUpdateFiled($updates, $data);
            //3.计算金额，补全
            $data = $this->calculationMoney($data);
            //4.解析平台数据，状态分析或平台类型解析，以及数据过滤等
            if (method_exists($this->plat, 'apiDataParse')) {
//                \Log::info('进入格式化方法的平台是'.$this->plat);
                $data = $this->plat->apiDataParse($apiData, $data);
            }

            //5.添加字段，查找网址名称并添加
            $data = $this->addField($adds, $data);
            //6.状态与金额规范化
            $data = $this->stateMoneyRelation($data);
            //7.添加api数据
            $data['api_data'] = json_encode($apiData);

            //8.删除原数据，赋值为变更后得数据（如果值为空，直接进入下次循环）
            unset($items[$k]);
            if (empty($data)) continue;
            $items[$k] = $data;

        }
        return $items;
    }

    /**
     * gameapi
     * 2018/9/20 21:27
     * Administrator
     * save
     * 更新或创建数据
     * @param array $items
     */
    public function save(array $items = [])
    {
        foreach ($items as $item) {
            try{
                $br = PlayerBetFlow::where('main_game_plat_code', $this->plat->platName)
                    ->where($this->plat->uniqueKey, $item[$this->plat->uniqueKey])
                    ->pluck($this->plat->uniqueKey)
                    ->toArray();

                if (empty($br)) {
                    PlayerBetFlow::create($item);
                } else {
                    PlayerBetFlow::where('main_game_plat_code', $this->plat->platName)
                        ->where($this->plat->uniqueKey, (string)$item[$this->plat->uniqueKey])
                        ->where(function ($query) use ($item) {
                            $query->where([['bet_amount', '!=', $item['bet_amount']],])
                                ->orWhere([['company_payout_amount', '!=', $item['company_payout_amount']],])
                                ->orWhere([['company_win_amount', '!=', $item['company_win_amount']],])
                                ->orWhere([['bet_flow_available', '!=', $item['bet_flow_available']],])
                                ->orWhere([['status', '!=', $item['status']],]);
                        }
                        )
                        ->update($item);
                }
            }catch (\Exception $e){

            }

        }
    }

    /**
     * gameapi
     * 2018/9/23 15:26
     * Administrator
     * 计算金额，补全
     * calculationMoney
     * @param $data
     * @return mixed
     */
    public function calculationMoney($data)
    {
        if (array_key_exists('bet_time', $data)) {
            if (substr_count($data['bet_time'], ':') > 0) {
                if (substr_count($data['bet_time'], '+') > 0) {
                    $data['bet_time'] = str_before($data['bet_time'], '+');
                }
                $data['bet_time'] = Carbon::parse($data['bet_time'], $this->plat->timezone)
                    ->timezone('Asia/Shanghai')
                    ->toDateTimeString();
            } else {
                if (strlen($data['bet_time']) == 13) {
                    $data['bet_time'] = $data['bet_time'] / 1000;
                }
                $betTime = Carbon::parse(date("Y-m-d H:i:s", $data['bet_time']), $this->plat->timezone);
                $betTime->timezone($this->defTimezone);
                $data['bet_time'] = $betTime->toDateTimeString();
            }

        }

        if (array_key_exists('bet_amount', $data)) {
            $data['bet_amount'] = abs($data['bet_amount']);
        }

        if (array_key_exists('company_payout_amount', $data)) 
        {
            
            if(isset($data['plat_type'])&&($data['plat_type']=='YOPLAY'||$data['plat_type']=='XIN'))
            {
                if($data['company_payout_amount']<0)
                {
                    $data['company_payout_amount']=$data['bet_amount']-abs($data['company_win_amount']);
                }
                else
                {
                    $data['company_payout_amount']=$data['bet_amount']+abs($data['company_win_amount']);
                }
            }
            else
            {
                 $data['company_payout_amount'] = abs($data['company_payout_amount']);
            }

        }

        //存在bet_amount,company_payout_amount，其它不存在
        if (array_key_exists('bet_amount', $data) && array_key_exists('company_payout_amount', $data) && !array_key_exists('available_bet_amount', $data) && !array_key_exists('company_win_amount', $data)) {
            $data['company_win_amount'] = $data['company_payout_amount'] - $data['bet_amount'];

            if ($data['company_win_amount'] == 0) {
                $data['available_bet_amount'] = 0;
            } else {
                $data['available_bet_amount'] = $data['bet_amount'];
            }

        }//存在bet_amount,company_win_amount，其它不存在
        elseif (array_key_exists('bet_amount', $data) && array_key_exists('company_win_amount', $data) && !array_key_exists('available_bet_amount', $data) && !array_key_exists('company_payout_amount', $data)) {
            if ($data['company_win_amount'] == 0) {
                $data['available_bet_amount'] = 0;
            } else {
                $data['available_bet_amount'] = $data['bet_amount'];
            }
            $data['company_payout_amount'] = $data['available_bet_amount'] + $data['company_win_amount'];

        }//存在bet_amount,company_win_amount,available_bet_amount，其它不存在
        elseif (array_key_exists('bet_amount', $data) && array_key_exists('company_win_amount', $data) && array_key_exists('available_bet_amount', $data) && !array_key_exists('company_payout_amount', $data)) {
            $data['company_payout_amount'] = $data['available_bet_amount'] + $data['company_win_amount'];
        } //存在bet_amount,company_win_amount,available_bet_amount，其它不存在
        elseif (array_key_exists('bet_amount', $data) && array_key_exists('company_win_amount', $data) && array_key_exists('company_payout_amount', $data) && !array_key_exists('available_bet_amount', $data)) {
            if ($data['company_win_amount'] == 0) {
                $data['available_bet_amount'] = 0;
            } else {
                $data['available_bet_amount'] = $data['bet_amount'];
            }
        }//存在bet_amount,company_payout_amount,available_bet_amount，其它不存在
        elseif (array_key_exists('bet_amount', $data) && array_key_exists('company_payout_amount', $data) && array_key_exists('available_bet_amount', $data) && !array_key_exists('company_win_amount', $data)) {
            if ($data['available_bet_amount'] == 0) {
                $data['company_win_amount'] = 0;
            } else {
                $data['company_win_amount'] = $data['company_payout_amount'] - $data['available_bet_amount'];
            }
        }

        //玩家输赢取反，转公司输赢
        if (array_key_exists('company_win_amount', $data)) {
            $data['company_win_amount'] = -$data['company_win_amount'];
        }

        return $data;
    }

    /**
     * gameapi
     * 2018/9/25 9:00
     * Administrator
     * getPlaerSite
     * @param $data
     * @return string
     */
    public function getPlayerSite($data): string
    {
        $mainGamePlat = MainGamePlat::where('main_game_plat_name', $this->plat->platName)->first();
        $player = Player::where([
                ['main_game_plats_id', '=', $mainGamePlat->id],
                ['username', '=', $data['username']],
            ]
        )->first();
        if ($player) {
            $siteName = $player->site()->first()->username;
        } else {
            $siteName = 'admin';
        }
        return $siteName;
    }

    /**
     * gameapi
     * 2018/9/25 9:04
     * Administrator
     * mapUpdateFiled
     * @param array $updates
     * @param $data
     * @return array
     */
    public function mapUpdateFiled(array $updates, $data): array
    {
        $oldKeys = array_keys($data);
        $updates = empty($updates) ? $this->plat->updateFiled : $updates;
        $keys = array_keys($updates);
        $deleteKeys = collect($oldKeys)->diff($keys)->toArray();
        $data = array_except($data, array_values($deleteKeys));

        //映射字段
        foreach ($updates as $updateFiled => $filed) {
            if (is_array($filed)) {
                foreach ($filed as $item) {
                    if (array_key_exists($updateFiled, $data)) {
                        $value = $data[$updateFiled];
                        $data[$item] = $value;
                    }
                }
                unset($data[$updateFiled]);
            } else {
                if (array_key_exists($updateFiled, $data)) {
                    $value = $data[$updateFiled];
                    unset($data[$updateFiled]);
                    $data[$filed] = $value;
                }
            }
        }
        return $data;
    }

    /**
     * gameapi
     * 2018/12/1 12:25
     * Administrator
     * addField
     * @param array $adds
     * @param $data
     * @return array
     */
    private function addField(array $adds, $data): array
    {
        $siteName = $this->getPlayerSite($data);
        $adds = empty($adds) ? $this->plat->adds : $adds;
        $adds = array_merge($adds, ['site_username' => $siteName]);
        $adds = array_merge($adds, ['line' => $this->plat->lineName]);
        $data = array_merge($data, $adds);

        return $data;
    }

    /**
     * gameapi
     * 2018/12/3 19:49
     * Administrator
     * stateMoneyRelation
     * @param $data
     * @return array
     */
    private function stateMoneyRelation($data): array
    {
        //撤单输赢和有效投注处理
        if ($data['status'] == -1) {
            $data = array_merge($data, ['bet_flow_available' => 0]);
            $data['company_win_amount'] = 0;
            $data['available_bet_amount'] = 0;
            $data['company_payout_amount'] = 0;
        } elseif ($data['status'] === 0) {
            $data = array_merge($data, ['bet_flow_available' => 1]);
            $data['company_win_amount'] = 0;
            $data['company_payout_amount'] = 0;
        } else {
            if (($data['company_win_amount'] == 0 && $data['available_bet_amount'] == 0)) {
                $data = array_merge($data, ['bet_flow_available' => 0]);
                $data['company_payout_amount'] = 0;
            } else {
                $data = array_merge($data, ['bet_flow_available' => 1]);
            }
        }
        return $data;
    }



}